package com.hboxs.asl.controller.wechat;

import com.hboxs.asl.entity.Giveaway;
import com.hboxs.asl.entity.Member;
import com.hboxs.asl.entity.Order;
import com.hboxs.asl.service.*;
import com.hboxs.asl.wechat.entity.WxOrder;
import com.hboxs.asl.wechat.payment.WxPayResultNotify;
import com.hboxs.asl.wechat.payment.base.WxPayData;
import com.hboxs.asl.wechat.payment.base.WxPayException;
import com.hboxs.asl.wechat.service.WxOrderService;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;

/**
 * Created by hboxs on 28/7/15.
 */
@Controller("wxPaymentController")
@RequestMapping("/wechat/payment")
public class WxPaymentController {
    protected Logger logger = Logger.getLogger(getClass());
    @Resource(name = "memberServiceImpl")
    private MemberService memberService;
    @Resource(name = "wxOrderServiceImpl")
    private WxOrderService wxOrderService;
    @Resource(name = "orderServiceImpl")
    private OrderService orderService;
    @Resource(name = "cartItemServiceImpl")
    private CartItemService cartItemService;
    @Resource(name = "giveawayServiceImpl")
    private GiveawayService giveawayService;
    @Resource(name = "tradeServiceImpl")
    private TradeService tradeService;


    /**
     * 微信支付结果回调通知<br>
     * 详见<a href='https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7'>https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7</a>
     *
     * @param request
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    @RequestMapping(value = "/result-notify", method = RequestMethod.POST)
    public
    @ResponseBody
    String resultNotify(HttpServletRequest request) throws IOException, DocumentException {
        InputStream inputStream = null;
        String response = null;

        try {
            WxPayResultNotify resultNotify = new WxPayResultNotify();

            // 从request中取得输入流
            inputStream = request.getInputStream();
            // 读取输入流
            SAXReader reader = new SAXReader();

            Document document = reader.read(inputStream);

            String xml = document.asXML();

            logger.info("WxPay Notify Result:" + xml);

            // 保存xml结果为key-value
            WxPayData data = resultNotify.getNotifyData(xml);

            WxPayData result = resultNotify.processNotify(data);

            WxOrder wxOrder = null;

            // 微信支付交易流水号
            if (data.isSet("transaction_id"))
                wxOrder = wxOrderService.findByTransactionId(data.getValue("transaction_id").toString());

            // 获取用户
            String openid = data.getValue("openid").toString();
            Member member = memberService.findByUsername(openid);
            // 消费金额（单位：分）
            String total_fee = data.getValue("total_fee").toString();
            // 消费金额（单位：元）
            BigDecimal amount = new BigDecimal(Long.valueOf(total_fee) / 100f);

            if (member != null
                    && result.getValue("return_code").toString().equals("SUCCESS")
                    && data.isSet("attach")
                    && wxOrder == null) {
                // 返回成功

                // 查找系统微信订单
                if (data.isSet("out_trade_no"))
                    wxOrder = wxOrderService.findByOutTradeNo(data.getValue("out_trade_no").toString());

                // 支付成功结果处理
                if (data.getValue("result_code").toString().equals("SUCCESS")) {
                    String attach = data.getValue("attach").toString();
                    // 充值处理
                    if (attach.equals("RECHARGE")) {
                        // 向购物车添加赠品项
                        Giveaway giveaway = giveawayService.find(wxOrder.getTotalFee());
                        if (giveaway != null) {
                            cartItemService.create(giveaway.getProduct(), 1, member.getCart(), new BigDecimal(0) , null);
                        }
                        // 更新用户账户余额
                        member.setBalance(member.getBalance().add(wxOrder.getTotalFee()));
                        memberService.update(member);
                        // 生成充值记录
                        tradeService.createRechargeTrade(member, wxOrder.getTotalFee());
                    } else {
                        // 订单支付处理
                        String[] str = attach.split(":");
                        if (str.length == 2) {
                            String sn = str[1];
                            if (sn != null) {
                                Order order = orderService.findBySn(sn);
                                if (order != null) {
                                    order.setPaymentStatus(Order.PaymentStatus.paid);
                                    // 支付完成，过期时间设置为空
                                    order.setExpire(null);
                                    orderService.update(order);
                                }
                            }
                        }
                    }
                }
                // 更新订单状态
                if (wxOrder != null) {
                    logger.debug("Updating Transaction ID!");
                    wxOrder.setTransactionId(data.getValue("transaction_id").toString());
                    wxOrder.setPaymentResult(data.getValue("result_code").toString());
                    wxOrder.setTradeType(data.getValue("trade_type").toString());
                    wxOrderService.update(wxOrder);
                }
            }
            response = result.toXml();
        } catch (WxPayException e) {
            e.printStackTrace();
            WxPayData data = new WxPayData();
            data.setValue("return_code", "FAIL");
            data.setValue("return_msg", e.getMessage());
            try {
                logger.error("Processing Notify Result Error:" + data.toXml());
                response = data.toXml();
            } catch (Exception ex) {
            }
        } finally {
            if (inputStream != null) try {
                inputStream.close();
            } catch (Exception e) {
            }
        }

        logger.info("Notify Result Response:" + response);

        return response;
    }

}
